import random
from simcell.cell.protein_bag import ProteinBag

class Cytosol:
    def __init__(self):
        self.proteins = ProteinBag()        
        self.rnas = RnaBag()

    def __str__(self):
        repr = "Rnas(%s)" % str(self.rnas)
        return repr

    def __repr__(self):
        repr  = "Rnas:\n"
        repr += "  " + "\n  ".join(self.rnas.__repr__().splitlines())
        repr += "\nProteins:\n"
        repr += "  " + "\n  ".join(self.proteins.__repr__().splitlines())
        return repr
        
    def addProtein(self, protein):
        self.proteins.insert(protein)
    
    def addRna(self, rna):
        self.rnas.insert(rna)
        
    def extractRandomRna(self):
        return self.rnas.extractRandomRna()
    
    
class RnaBag:
    """Bolsa de rna"""
  
    def __init__(self):
        self.bag = {}
        self.total = 0
        self.weight = 0
        # self.volume = 0 
    
    def extractRandomRna(self):
        if self.total > 0:            
            i = random.randint(0, self.total-1)
            acum = 0
            for rna, num in self.bag.values():
                acum += num
                if i < acum:
                    rna1 = self.extract(rna)
                    return rna1
        return None
    
    def buildKey(self, rna):
        return "".join(map(str, rna.strand))
        
    def insert(self, rna):
        self.insertN(rna, 1)
  
    def insertN(self, rna, n):
        # self.volume += n * len(proteina)
        rna_key = self.buildKey(rna)        
        if self.bag.has_key(rna_key):
            rna, num = self.bag[rna_key]
            rna_data = (rna, num + n)
            self.bag[rna_key] = rna_data            
        else:
            self.bag[rna_key] = (rna, 1)
        
        self.total += n
        self.weight += n * len(rna.strand)
  
    def extractN(self, rna, n):
        rna_key = self.buildKey(rna)    
        n_real = min(n, self.getAmountOfRna(rna_key))
        if n_real > 0:
            rna, num = self.bag[rna_key]
            self.bag[rna_key] = (rna, num - n_real)
            rnas = [rna for _ in range(n_real)]
            
            self.total -= n_real
            self.weight -= n_real * len(rna.strand)
            
            return rnas
        else:
            return []
        # self.volume -= len(rna)
    
    def extract(self, rna):
        rnas = self.extractN(rna, 1)
        if len(rnas) > 0:
            return rnas[0]
        else:
            return None
        
    def getAmountOfRna(self, rna_key):
        # rna_key = self.buildKey(rna)
        if self.bag.has_key(rna_key):            
            return self.bag[rna_key][1]
        else:
            return 0  
  
    # def getVolume(self):
        # """ devuelve el volumen de la bolsa"""
        # return self.volume
    def __str__(self):
        repr = "types:%d total:%d weight:%d" % (len(self.bag), self.total, self.weight)
        return repr
        
    def __repr__(self):
        repr = str(self)
        repr += "\n" + "\n".join(map(lambda x: str(self.bag[x][1]) + ' ' + str(x), self.bag))
        return repr